package com.travel.recommend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.travel.common.attraction.AttractionTagMap;
import com.travel.common.to.AttractionInfoTo;
import com.travel.recommend.entity.*;
import com.travel.recommend.feign.SightFeignService;
import com.travel.recommend.service.*;
import com.travel.recommend.strategyPattern.DefaultHotRecommendationStrategy;
import com.travel.recommend.strategyPattern.RecommendationStrategy;
import com.travel.recommend.strategyPattern.TagRecommendationStrategy;
import com.travel.recommend.strategyPattern.UserBehaviorRecommendationStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class RecommendServiceImpl implements RecommendService {

    @Autowired
    DecayFunctionService decayFunctionService;

    @Autowired
    RecommendParameterService recommendParameterService;

    @Autowired
    SimilarityConfigService similarityConfigService;

    @Autowired
    UserBehaviorWeightService userBehaviorWeightService;

    static double locationWeight; //计算景点相似度中，地理位置权重
    static double tagPopularityWeight; //计算景点相似度中，景点标签权重
    static double likeCollectionCommentWeight; //计算景点相似度中，点赞/收藏/评论权重
    static double clicksWeight; //计算景点相似度中，被点击次数权重

    static int policyDivision; //策略划分值(用户行为数)，<基于标签，>=协同过滤
    static int similarityAttractionNum; //附加几个相似度高的景点
    static int neighboringNum; //基于用户行为，寻找几个最邻近用户

    static double likeWeight; //基于用户行为，点赞权重
    static double collectionWeight; //基于用户行为，收藏权重
    static double commentWeight; //基于用户行为，评论权重
    static double clicksWeight1; //基于用户行为,点击次数系数

    static double init; //热度衰减函数，初始值，上限
    static int m; //热度衰减函数，天数，x轴长度
    static double finish; //热度衰减函数，最低值，下限


    @Autowired
    SightFeignService sightFeignService;

    @Autowired
    InitialLikeTagService initialLikeTagService;

    @Autowired
    UserAttractionWeightService userAttractionWeightService;

    @Autowired
    TagPopularityService tagPopularityService;

    @Autowired
    UserTagWeightService userTagWeightService;


    /**
     * 推荐总方法
     *
     * @param userId
     * @return
     */
    @Override
    public List<Integer> recommed(Integer userId) {
        //1.加载推荐算法的配置信息
        initAlgorithmConfig();

        log.info("===当前的配置信息===");
        log.info("locationWeight===" + locationWeight);
        log.info("tagWeight===" + tagPopularityWeight);
        log.info("likeCollectionCommentWeight===" + likeCollectionCommentWeight);
        log.info("clicksWeight===" + clicksWeight);

        log.info("policyDivision===" + policyDivision);
        log.info("similarityAttractionNum===" + similarityAttractionNum);
        log.info("neighboringNum===" + neighboringNum);

        log.info("likeWeight===" + likeWeight);
        log.info("collectionWeight===" + collectionWeight);
        log.info("commentWeight===" + commentWeight);
        log.info("clicksWeight1===" + clicksWeight1);

        log.info("init===" + init);
        log.info("m===" + m);
        log.info("finish===" + finish);
        log.info("==================");

        //2.统计用户的行为次数总和（点赞+收藏+评论）
        Integer behaviorNum = sightFeignService.getBehaviorNum(userId);
//        Integer behaviorNum = 20;
//        Integer behaviorNum = 0; // 用户无行为 模拟
        System.out.println("用户的行为次数总和==" + behaviorNum);

        //3.获取该用户的初始喜好景点标签
        InitialLikeTagEntity entity = initialLikeTagService.getOne(new QueryWrapper<InitialLikeTagEntity>().eq("user_id", userId));
        String initialTag = null;
        if(entity != null){
            initialTag = entity.getInitialTag();
        }
//        String initialTag = null; // 用户无初始喜好标签 模拟

        List<Integer> recommendIdList;
        RecommendationStrategy strategy = null;
        //4. 用户行为次数 < policyDivision -> 基于景点标签
        if (behaviorNum < policyDivision) {
            //4.1 无初始喜好标签
            if (initialTag == null) {
                //4.1.1 无行为 -> 默认热门推荐
                if (behaviorNum == 0) {
                    strategy = new DefaultHotRecommendationStrategy();
                } else { //4.1.2 有行为 -> 基于景点标签
                    strategy = new TagRecommendationStrategy(initialLikeTagService,sightFeignService,
                            userTagWeightService,tagPopularityService,userAttractionWeightService,
                            recommendParameterService,similarityConfigService);
                }
            } else { //4.2 有初始喜好标签 无论是否有行为 -> 基于标签推荐
                strategy = new TagRecommendationStrategy(initialLikeTagService,sightFeignService,
                        userTagWeightService,tagPopularityService,userAttractionWeightService,
                        recommendParameterService,similarityConfigService);
            }
        } else { //4.3 用户行为 >= policyDivision -> 基于用户协同过滤
            strategy = new UserBehaviorRecommendationStrategy(initialLikeTagService,sightFeignService,
                    userTagWeightService,tagPopularityService,userAttractionWeightService,
                    recommendParameterService,similarityConfigService,userBehaviorWeightService);
        }

        recommendIdList = strategy.recommend(userId);

        if(recommendIdList == null){
            log.info("找不到最邻近用户 使用基于标签推荐算法");
            // 找不到最邻近用户 使用基于标签推荐算法
            strategy = new TagRecommendationStrategy(initialLikeTagService,sightFeignService,
                    userTagWeightService,tagPopularityService,userAttractionWeightService,
                    recommendParameterService,similarityConfigService);
            recommendIdList = strategy.recommend(userId);
        }

        System.out.println("推荐景点id的list===" + recommendIdList);

        return recommendIdList;
    }

    /**
     * 加载推荐算法的配置信息
     */
    public void initAlgorithmConfig() {
        DecayFunctionEntity decayFunctionEntity = decayFunctionService.getNowDecayFunction();
        RecommendParameterEntity recommendParameterEntity = recommendParameterService.getNowRecommendParameter();
        SimilarityConfigEntity similarityConfigEntity = similarityConfigService.getNowSimilarityConfig();
        UserBehaviorWeightEntity userBehaviorWeightEntity = userBehaviorWeightService.getNowUserBehaviorWeight();

        locationWeight = similarityConfigEntity.getLocationWeight(); //计算景点相似度中，地理位置权重
        tagPopularityWeight = similarityConfigEntity.getTagPopularityWeight(); //计算景点相似度中，景点标签权重
        likeCollectionCommentWeight = similarityConfigEntity.getLikeCollectionCommentWeight(); //计算景点相似度中，点赞/收藏/评论权重
        clicksWeight = similarityConfigEntity.getClicksWeight(); //计算景点相似度中，被点击次数权重

        similarityAttractionNum = recommendParameterEntity.getSimilarityAttractionNum(); //基于标签，附加几个相似度高的景点
        neighboringNum = recommendParameterEntity.getNeighboringNum(); //基于用户行为，寻找几个最邻近用户
        policyDivision = recommendParameterEntity.getPolicyDivision(); //策略划分值(用户行为数)，<基于标签，>=协同过滤

        likeWeight = userBehaviorWeightEntity.getLikeWeight(); //基于用户行为，点赞权重
        collectionWeight = userBehaviorWeightEntity.getCollectionWeight(); //基于用户行为，收藏权重
        commentWeight = userBehaviorWeightEntity.getCommentWeight(); //基于用户行为，评论权重
        clicksWeight1 = userBehaviorWeightEntity.getClicksWeight(); //基于用户行为,点击次数系数

        init = decayFunctionEntity.getInit(); //热度衰减函数，初始值，上限
        m = decayFunctionEntity.getM(); //热度衰减函数，天数，x轴长度
        finish = decayFunctionEntity.getFinish(); //热度衰减函数，最低值，下限


    }


}
